using System;
using System.Collections.Generic;
using System.Linq;
using System;
using Microsoft.Xna.Framework.Design;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.IO;

namespace WindowsGame1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        #region member variables
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;



        private SpriteFont _defaultFont;

        private Vector4 _boddenHeader;

        private List <Vectorfield> _boddenData = new List<Vectorfield>();

        private System.Drawing.Bitmap _DataImage;

        private int step = 0;

        private Streamline stream;
        private Player _playerOne;
        private LineList myLineList;

        List<Vector2> start;

        parseCSV BoddenCSV;



        #endregion

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here 

            myLineList = new LineList(this);
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here

            //initialize LineList
            myLineList.LoadContent(GraphicsDevice);


            BoddenCSV = new parseCSV("Content\\bodden.txt");
            _boddenHeader = BoddenCSV.HeaderData;
            //Vectorfield temp = new Vectorfield(step, (int)_boddenHeader.X, (int)_boddenHeader.Y, BoddenCSV.DataArray);
            _boddenData.Add(new Vectorfield(step, (int)_boddenHeader.X, (int)_boddenHeader.Y, BoddenCSV.DataArray, this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height));

            _DataImage = new System.Drawing.Bitmap((int)_boddenHeader.X, (int)_boddenHeader.Y);

            _defaultFont = this.Content.Load<SpriteFont>("DefaultFont");       

            
            _playerOne = new Player(this.Content.Load<Texture2D>("test"), new Vector2(0.0f, 0.0f));

            //Set start Vectors for streamlines
            start = new List<Vector2>();

            for (int x = 0; x < this.GraphicsDevice.Viewport.Width - 25; x += 25)
            {
                for (int y = 0; y < this.GraphicsDevice.Viewport.Height - 25; y += 25)
                {
                    start.Add(new Vector2(x, y));
                }

            }
            //initialize streamlines
            stream = new Streamline(_boddenData.ElementAt(step));
            stream.Calculate(start, 800);
            
           
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (_playerOne.currentState.Buttons.Back == ButtonState.Pressed)
            {
                GamePad.SetVibration(PlayerIndex.One, 0.0f, 0.0f);
                this.Exit();
            }

            if (_playerOne.currentState.Buttons.A == ButtonState.Pressed && _playerOne.lastState.Buttons.A == ButtonState.Released)
            {
                step = (step + 1) % 9;
                
                //initialize streamlines
                _boddenData.Add(new Vectorfield(step, (int)_boddenHeader.X, (int)_boddenHeader.Y, BoddenCSV.DataArray, this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height));

                stream = new Streamline(_boddenData.ElementAt(step));
                stream.Calculate(start, 800);
            }
            else if (_playerOne.currentState.Buttons.B == ButtonState.Pressed && _playerOne.lastState.Buttons.B == ButtonState.Released)
            {

                step = Math.Abs(step - 1) % 9;

                    //initialize streamlines
                    _boddenData.Add(new Vectorfield(step, (int)_boddenHeader.X, (int)_boddenHeader.Y, BoddenCSV.DataArray, this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height));

                    stream = new Streamline(_boddenData.ElementAt(step));
                    stream.Calculate(start, 800);
            }

            //make sure player is not out of bounds!
            _playerOne.position = new Vector2(  MathHelper.Clamp(_playerOne.position.X, 0.0f, this.GraphicsDevice.Viewport.Width -1), 
                                                MathHelper.Clamp(_playerOne.position.Y, 0.0f, this.GraphicsDevice.Viewport.Height -1));
            
            //update Player 
            _playerOne.update(_boddenData[0].getDataVectorAt(_playerOne.position, true).direction, _boddenData[0].getDataVectorAt(_playerOne.position, true).pressure);


            

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            
            GraphicsDevice.Clear(Color.Black);
            GraphicsDevice.RenderState.CullMode = CullMode.None;
            
            // TODO: Add your drawing code here
            spriteBatch.Begin();

            //// Find the center of the string
            //Vector2 FontOrigin = _defaultFont.MeasureString(_testText) / 2;
            // Draw the string
            spriteBatch.DrawString(_defaultFont, _playerOne.vibration.ToString() + " Step:  " + step.ToString(), new Vector2(50, graphics.GraphicsDevice.Viewport.Height - 30),
                Color.LightGreen,
                0, new Vector2(0.0f, 0.0f), 1.0f, SpriteEffects.None, 0.5f);
    
            
            
            //using (MemoryStream memStream = new MemoryStream())
            //{
            //    _DataImage.Save(memStream, System.Drawing.Imaging.ImageFormat.Png);
            //    memStream.Seek(0, SeekOrigin.Begin); //must do this, or error is thrown in next line
            //    testTexture = Texture2D.FromFile(GraphicsDevice, memStream);
              
            //}
            //spriteBatch.Draw(testTexture, new Vector2(this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height), Color.White);

            //draw streamlines
            stream.Draw(spriteBatch, graphics.GraphicsDevice, myLineList, gameTime);

            _playerOne.draw(spriteBatch);


            spriteBatch.End();

            base.Draw(gameTime);
        }

    }
}
